package nl.ekok.Kentekencheck;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import android.os.Handler;
import android.os.Message;

public class AutoweekFetcher extends Thread {

	public static final int RESULT_OK = 0;
	public static final int RESULT_ERROR = 1;
	public static final int RESULT_NO_VALID_RESPONSE = 2;
	
	public static final String AUTOWEEK_URL = "http://www.autoweek.nl/kentekencheck.php";
	public static final String AUTOWEEK_KENTEKEN = "kenteken";
	public static final String AUTOWEEK_UNIQUE_OK_ID = "Technische gegevens";
	
	private Handler callback;
	private String query;
	
	public AutoweekFetcher(Handler callback, String query) {
		this.callback = callback;
		this.query = query;
	}

	@Override
	public void run() {

		try {
			// Start a HTTP POST request
			HttpPost httppost = new HttpPost(AUTOWEEK_URL);
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
			params.add(new BasicNameValuePair(AUTOWEEK_KENTEKEN, query));
			
			httppost.setEntity(new UrlEncodedFormEntity(params));
			HttpResponse response = httpclient.execute(httppost);

			// Parse the server response
			InputStream instream = response.getEntity().getContent();
			String result = ConvertStreamToString(instream);
			
			// First check the integrity of the response
			if (IsValidDetailsResponse(result)) {
				
				// Build info object with all the car's details
				Auto auto = BuildCarDetailsObject(result);
				
				// Return the found car details
				Message msg = Message.obtain();
				msg.obj = auto;
				msg.what = RESULT_OK;
				callback.sendMessage(msg);
				
				// Close connection
				httpclient.getConnectionManager().shutdown();
				
			} else {
				
				// No valid page returned
				callback.sendEmptyMessage(RESULT_NO_VALID_RESPONSE);
			}
			
		} catch (ClientProtocolException e) {
			callback.sendEmptyMessage(RESULT_ERROR);
			e.printStackTrace();
		} catch (IOException e) {
			callback.sendEmptyMessage(RESULT_ERROR);
			e.printStackTrace();
		}	
		
	}
	
	private boolean IsValidDetailsResponse(String response) {
		
		// Basically only checks for a unique string that should be in the response page's HTML content somewhere
		return (response.indexOf(AUTOWEEK_UNIQUE_OK_ID) >= 0);
		
	}
	
	private Auto BuildCarDetailsObject(String rs) {
		
		// This searches for all the needed string in the response HTML
		// WARNING: This is HIGHLY sensitive to even minor changes in Autoweek's generated HTML... :-(
		int sKenteken = rs.indexOf("<!-- ckentekendatablock -->");

		int sSignalement = rs.indexOf("SIGNALEMENT");
		int sSignalementMerk = rs.indexOf("Merk", sSignalement);
		int sSignalementModel = rs.indexOf("Model", sSignalement);
		
		int sGewichten = rs.indexOf("GEWICHTEN");
		int sGewichtenGewicht = rs.indexOf("Massa leeg", sGewichten);

		int sMotor = rs.indexOf("MOTOR</td></tr>		<tr style=\"background-color:#e5e5e5\">");
		
		// If no technical info is available:
		if (sMotor < 0) {

			return new Auto(
					rs.substring(sKenteken + 210, sKenteken + 218),
					rs.substring(sSignalementMerk + 100, rs.indexOf("</td></tr>", sSignalementMerk + 100)),
					rs.substring(sSignalementModel + 101, rs.indexOf("</td></tr>", sSignalementModel + 101)).replace(";", ""),
					rs.substring(sGewichtenGewicht + 106, rs.indexOf("</td></tr>", sGewichtenGewicht + 106)));
					
		}
		
		int sMotorCilinders = rs.indexOf("Cilinders", sMotor);
		int sMotorInhoud = rs.indexOf("Cilinderinhoud", sMotor);
		int sMotorVermogen = rs.indexOf("Maximaal vermogen", sMotor);
		int sMotorKoppel = rs.indexOf("Maximaal koppel", sMotor);
		
		int sPrestaties = rs.indexOf("PRESTATIES");
		int sPrestatiesTopSnelheid = rs.indexOf("Topsnelheid", sPrestaties);
		int sPrestatiesAcceleratie = rs.indexOf("Acceleratie", sPrestaties);
		
		// Create with full technical info:
		return new Auto(
				rs.substring(sKenteken + 210, sKenteken + 218),
				rs.substring(sSignalementMerk + 100, rs.indexOf("</td></tr>", sSignalementMerk + 100)),
				rs.substring(sSignalementModel + 101, rs.indexOf("</td></tr>", sSignalementModel + 101)).replace(";", ""),
				
				rs.substring(sMotorCilinders + 105, rs.indexOf("</td></tr>", sMotorCilinders + 105)),
				rs.substring(sMotorInhoud + 110, rs.indexOf("</td></tr>", sMotorInhoud + 110)),
				rs.substring(sMotorVermogen + 113, rs.indexOf("</td></tr>", sMotorVermogen + 113)),
				rs.substring(sMotorKoppel + 111, rs.indexOf("</td></tr>", sMotorKoppel + 111)),
				
				rs.substring(sGewichtenGewicht + 106, rs.indexOf("</td></tr>", sGewichtenGewicht + 106)),
				rs.substring(sPrestatiesTopSnelheid + 107, rs.indexOf("</td></tr>", sPrestatiesTopSnelheid + 107)),
				rs.substring(sPrestatiesAcceleratie + 118, rs.indexOf("</td></tr>", sPrestatiesAcceleratie + 118)));
	}

    private static String ConvertStreamToString(InputStream is) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
 
        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
    
}
